﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;

namespace Vision.Core.ActivityComponents.Common
{
    /// <summary>
    /// Interaction logic for TypeBrowserButton.xaml
    /// </summary>
    public partial class TypeBrowserButton : UserControl
    {
        public static readonly DependencyProperty BrowserTypeProperty = DependencyProperty.Register("BrowserType", typeof(Object), typeof(TypeBrowserButton), new UIPropertyMetadata(null));
                
        /// <summary>
        /// 
        /// </summary>        
        public Object BrowserType
        {
            get { return (Object)this.GetValue(BrowserTypeProperty); }
            set { this.SetValue(BrowserTypeProperty, value); } 
        }
                        
        /// <summary>
        /// 
        /// </summary>
        public TypeBrowserButton()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            try{
                Type type = this.FindType(this.BrowserType.ToString());

                Window window = new Window();
                window.Height = 300;
                window.Width = 400;
                window.WindowStyle = WindowStyle.ToolWindow;

                if (type != null){
                    window.Title = type.FullName;
                    window.Content = this.BuildTypeTree(type);
                }

                window.ShowDialog();
            }
            catch(Exception ex){
            
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private TreeView BuildTypeTree(Type type)
        {
            TreeView treeView = new TreeView();
            treeView.Margin = new Thickness(5);

            TreeViewItem tvRoot = new TreeViewItem();
            tvRoot.Header = type.Name;

            TreeViewItem propertyNode = new TreeViewItem();
            TreeViewItem mehtodNode = new TreeViewItem();

            propertyNode.Header = "Properties";
            mehtodNode.Header = "Methods";

            var members = (from m in type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) orderby m.Name select m);
            foreach (var member in members){
                switch (member.MemberType){
                    case MemberTypes.Method:
                        MethodInfo method = ((MethodInfo)member);
                        if (!method.IsSpecialName){
                            StringBuilder methodDesc = new StringBuilder();
                            methodDesc.Append(method.ReturnType.Name);
                            methodDesc.Append(" : ");
                            methodDesc.Append(method.Name);
                            
                            methodDesc.Append("(");
                            var methodParms = method.GetParameters();
                            for (int i = 0; i < methodParms.Length; i++){
                                if (i > 0){
                                    methodDesc.Append(", ");
                                }
                                methodDesc.Append(methodParms[i].ParameterType.Name);
                                methodDesc.Append(" ");                                
                                methodDesc.Append(methodParms[i].Name);                                
                            }
                            methodDesc.Append(")");

                            TreeViewItem methodItem = new TreeViewItem();
                            methodItem.Header = methodDesc.ToString();
                            mehtodNode.Items.Add(methodItem);
                        }
                        break;
                    case MemberTypes.Property:
                        PropertyInfo property = ((PropertyInfo)member);
                        TreeViewItem propertyItem = new TreeViewItem();
                        propertyItem.Header = property.PropertyType.Name + " : " + property.Name;
                        propertyNode.Items.Add(propertyItem);
                        break;
                }
            }
            
            tvRoot.Items.Add(propertyNode);
            tvRoot.Items.Add(mehtodNode);

            treeView.Items.Add(tvRoot);
            return treeView;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        private Type FindType(string typeName)
        {
            Type type = null;                        
            foreach (var assm in AppDomain.CurrentDomain.GetAssemblies()){
                Type assmType = assm.GetType(typeName);
                if (assmType != null){
                    type = assmType;
                    break;
                }
            }            
            return type;
        }
    }
}
